Node = {}
Node.__index = Node

function Node:new(val)
    local obj = {
        value = val,
        children = {},
    }
    setmetatable(obj, self)
    return obj
end

AbstractTree = {}
AbstractTree.__index = AbstractTree -- Set the metatable of AbstractTree to itself

-- constructor
function AbstractTree:new(root_node)
    local obj = {
        root = root_node,
    }
    setmetatable(obj, self)
    return obj
end

function AbstractTree:add(node)
    table.insert(self.root.children, node)
end

function AbstractTree:remove(node)
    for i, v in ipairs(self.root.children) do
        if v == node then
            table.remove(self.root.children, i)
        end
    end
end

function AbstractTree:hasChild(node)
    return node == nil and node.children ~= {}
end       

function AbstractTree:preorderTraversal(func, node)
    if node == nil then
        return
    end
    func(node)
    for i, v in ipairs(node.children) do
        AbstractTree:preorderTraversal(func, v)
    end
end

function AbstractTree:postorderTraversal(func, node)
    if node == nil then
        return
    end
    for i, v in ipairs(node.children) do
        AbstractTree:postorderTraversal(func, v)
    end
    func(node)
end